package com.okaixz.manager.utils;

import com.google.gson.annotations.SerializedName;
import okhttp3.*;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.List;

/**
 * App下单
 */
public class AppPrepay {
    private static String HOST = "https://api.mch.weixin.qq.com";
    private static String METHOD = "POST";
    private static String PATH = "/v3/pay/transactions/app";
    /**
     * 商户号
     */
    public static String merchantId = "1723726326";
    /**
     * appid
     */
    public static String appId = "wx3453489b33bf938d";
    /**
     * 商户API私钥路径
     */
    public static String privateKeyPath = "C:\\Users\\yxky-077\\Downloads\\WXCertUtil\\cert\\1723726326_20250801_cert\\apiclient_key.pem";
    /**
     * 商户API公钥路径
     */
//    public static String pubKeyPath = "C:\\Users\\yxky-077\\Downloads\\WXCertUtil\\cert\\1723726326_20250801_cert\\wechatpay_1D571615195FA455339C4E6889730B768804C19B.pem";
    public static String pubKeyPath = "C:\\Users\\yxky-077\\Downloads\\WXCertUtil\\cert\\1723726326_20250801_cert\\wechatpay_1D571615195FA455339C4E6889730B768804C19B.pem";

    public static String wechatPayPublicKeyIdNew = "PUB_KEY_ID_0117237263262025080100192010000201";
    /**
     * 商户证书序列号
     */
    public static String merchantSerialNumber = "6BAEEC6282486325A307B9961587B0840891D707";
    //  /**
    //  * 商户API私钥路径
    //  */
    //  public static String privateKeyPath = "/usr/local/okai-server/apiclient_key.pem";
    //  /**
    //   * 商户APIV3密钥
    //   */
    //  public static String apiV3Key = "eN6wU6jI4yW2kW0kF8fG6vC7oU4mV3cX";

    //    /**
    //     * 支付通知回调地址
    //     */
    //    public static String notify_url = "https://ux328251nc8.vicp.fun/wx/native_pay_callback";
    /**
     * 支付通知回调地址
     */
    public static String notify_url = "https://www.okaixz.com/api/wx/native_pay_callback";

    public static void main(String[] args) {
        // TODO: 请准备商户开发必要参数，参考：https://pay.weixin.qq.com/doc/v3/merchant/4013070756
        AppPrepay client = new AppPrepay(
                merchantId,                    // 商户号，是由微信支付系统生成并分配给每个商户的唯一标识符，商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756
                merchantSerialNumber,         // 商户API证书序列号，如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053
                privateKeyPath,    // 商户API证书私钥文件路径，本地文件路径
                wechatPayPublicKeyIdNew,      // 微信支付公钥ID，如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816
                pubKeyPath        // 微信支付公钥文件路径，本地文件路径
        );

        CommonPrepayRequest request = new CommonPrepayRequest();
        request.appid = "wx3453489b33bf938d";
        request.mchid = merchantId;
        request.description = "Image形象店-深圳腾大-QQ公仔";
        request.outTradeNo = "100000";
        request.timeExpire = "2025-08-08T10:34:56+08:00";
        request.attach = "自定义数据说明";
        request.notifyUrl = notify_url;
//        request.goodsTag = "WXG";
        request.supportFapiao = false;
        request.amount = new CommonAmountInfo();
        request.amount.total = 1L;//100是一元
        request.amount.currency = "CNY";
//        request.detail = new CouponInfo();
//        request.detail.costPrice = 1L;
//        request.detail.invoiceId = "wx123";
//        request.detail.goodsDetail = new ArrayList<>();
//        {
//            GoodsDetail item0 = new GoodsDetail();
//            item0.merchantGoodsId = "1246464644";
//            item0.wechatpayGoodsId = "1001";
//            item0.goodsName = "iPhone6s 16G";
//            item0.quantity = 1L;
//            item0.unitPrice = 528800L;
//            request.detail.goodsDetail.add(item0);
//        }
        ;
//        request.sceneInfo = new CommonSceneInfo();
//        request.sceneInfo.payerClientIp = "14.23.150.211";
//        request.sceneInfo.deviceId = "013467007045764";
//        request.sceneInfo.storeInfo = new StoreInfo();
//        request.sceneInfo.storeInfo.id = "0001";
//        request.sceneInfo.storeInfo.name = "腾讯大厦分店";
//        request.sceneInfo.storeInfo.areaCode = "440305";
//        request.sceneInfo.storeInfo.address = "广东省深圳市南山区科技中一道10000号";
//        request.settleInfo = new SettleInfo();
//        request.settleInfo.profitSharing = false;
        try {
            DirectAPIv3AppPrepayResponse response = client.run(request);

            // TODO: 请求成功，继续业务逻辑
            System.out.println(response);
        } catch (WXPayUtility.ApiException e) {
            // TODO: 请求失败，根据状态码执行不同的逻辑
            e.printStackTrace();
        }
    }

    public DirectAPIv3AppPrepayResponse run(CommonPrepayRequest request) {
        String uri = PATH;
        String reqBody = WXPayUtility.toJson(request);

        Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
        reqBuilder.addHeader("Accept", "application/json");
        reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
        reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo, privateKey, METHOD, uri, reqBody));
        reqBuilder.addHeader("Content-Type", "application/json");
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
        reqBuilder.method(METHOD, requestBody);
        Request httpRequest = reqBuilder.build();

        // 发送HTTP请求
        OkHttpClient client = new OkHttpClient.Builder().build();
        try (Response httpResponse = client.newCall(httpRequest).execute()) {
            String respBody = WXPayUtility.extractBody(httpResponse);
            if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
                // 2XX 成功，验证应答签名
                WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey,
                        httpResponse.headers(), respBody);

                // 从HTTP应答报文构建返回数据
                return WXPayUtility.fromJson(respBody, DirectAPIv3AppPrepayResponse.class);
            } else {
                throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
            }
        } catch (IOException e) {
            throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
        }
    }

    private final String mchid;
    private final String certificateSerialNo;
    private final PrivateKey privateKey;
    private final String wechatPayPublicKeyId;
    private final PublicKey wechatPayPublicKey;

    public AppPrepay(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) {
        this.mchid = mchid;
        this.certificateSerialNo = certificateSerialNo;
        this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath);
        this.wechatPayPublicKeyId = wechatPayPublicKeyId;
        if (wechatPayPublicKeyFilePath != null) {
            this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
        }else {
            this.wechatPayPublicKey=null;
        }
    }

    public static class SettleInfo {
        @SerializedName("profit_sharing")
        public Boolean profitSharing;
    }

    public static class CommonAmountInfo {
        @SerializedName("total")
        public Long total;

        @SerializedName("currency")
        public String currency;
    }

    public static class CommonSceneInfo {
        @SerializedName("payer_client_ip")
        public String payerClientIp;

        @SerializedName("device_id")
        public String deviceId;

        @SerializedName("store_info")
        public StoreInfo storeInfo;
    }

    public static class DirectAPIv3AppPrepayResponse {
        @SerializedName("prepay_id")
        public String prepayId;
    }

    public static class GoodsDetail {
        @SerializedName("merchant_goods_id")
        public String merchantGoodsId;

        @SerializedName("wechatpay_goods_id")
        public String wechatpayGoodsId;

        @SerializedName("goods_name")
        public String goodsName;

        @SerializedName("quantity")
        public Long quantity;

        @SerializedName("unit_price")
        public Long unitPrice;
    }

    public static class CouponInfo {
        @SerializedName("cost_price")
        public Long costPrice;

        @SerializedName("invoice_id")
        public String invoiceId;

        @SerializedName("goods_detail")
        public List<GoodsDetail> goodsDetail;
    }

    public static class StoreInfo {
        @SerializedName("id")
        public String id;

        @SerializedName("name")
        public String name;

        @SerializedName("area_code")
        public String areaCode;

        @SerializedName("address")
        public String address;
    }

    public static class CommonPrepayRequest {
        @SerializedName("appid")
        public String appid;

        @SerializedName("mchid")
        public String mchid;

        @SerializedName("description")
        public String description;

        @SerializedName("out_trade_no")
        public String outTradeNo;

        @SerializedName("time_expire")
        public String timeExpire;

        @SerializedName("attach")
        public String attach;

        @SerializedName("notify_url")
        public String notifyUrl;

        @SerializedName("goods_tag")
        public String goodsTag;

        @SerializedName("support_fapiao")
        public Boolean supportFapiao;

        @SerializedName("amount")
        public CommonAmountInfo amount;

        @SerializedName("detail")
        public CouponInfo detail;

        @SerializedName("scene_info")
        public CommonSceneInfo sceneInfo;

        @SerializedName("settle_info")
        public SettleInfo settleInfo;
    }
}
